/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package FEMSolver;

import BounderyPack.Boundery;
import BounderyPack.DBoundery;
import BounderyPack.DirihletPair;
import HashMatrix2.HashMatrix2;
import HashMatrix2.LUFactorization;
import MathLib.triangulation.SaveStructures.Node;
import java.awt.Toolkit;
import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JProgressBar;
import javax.swing.JTextArea;
import javax.swing.SwingWorker;

/**
 *
 * @author mark_o
 */
public class MyPenaltyIterationOld extends SwingWorker< Void,Void> {




    protected double h;
    protected double eps;
    protected double[] b;
    protected HashMatrix2 A;
    JProgressBar pb;
    JTextArea Text;
    public String outPath;
    DirihletPair [] mas;
    public static int MaxIter;

    protected ArrayList<DBoundery> NodeList;
    private double[] u1;

    public MyPenaltyIterationOld(double h, double eps, double[] b, HashMatrix2 A, ArrayList<DBoundery> NodeList,JTextArea Text,DirihletPair [] mas) {
        this.h = h;
        this.eps = eps;
        this.b = b;
        this.A = A;
        this.NodeList = NodeList;
        this.Text = Text;
        this.mas = mas;
    }

    private double penalty(double ui,int i){
        for (int j = 0; j < NodeList.size(); j++) {
            DBoundery boundery = NodeList.get(j);
            if(boundery.contains(i)){
                //System.out.println("зайшли в штраф  "+i);
                return Math.max((ui), h);////////////////////////////////////////////////////////////////

            }else{
                return ui;
            }
        }
        return 0;
    }

    private boolean check(double[] u1,double[] u2){
        boolean key = true;
        //System.out.println("перевірка:");
        for(int i=0;i<u1.length;i++){
            //System.out.println(Math.abs(u1[i]-u2[i]));
            if(Math.abs(u1[i]-u2[i])>eps){
                key = false;
                break;
            }
        }

        /*if(key){
        for(int i=0;i<u1.length;i++){
        if(Math.abs( penalty(u0[i], i))>eps){
        key = false;
        System.out.println(penalty(u0[i], i));
        break;
        }
        }
        }*/
        return key;
    }

    double[] u0;
    int iTemp;

    @Override
    protected  Void doInBackground(){

        u0 = new double[b.length];

        Text.append("\nПочаток обрахунку першого наближення");
        LUFactorization lu = new LUFactorization(A);




        u0 = lu.calculate(b); //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        
        //u0=new double[]{3.125487127960415 ,      4.999998161215734 ,       4.999998027311023        ,3.0934429329551407        ,3.0940930175322783        ,3.0933828420436615        ,3.125418472883064        ,4.999997959804245    ,3.0548010506228045        ,3.064936716636373        ,3.0535106939217385     ,3.0768203732497836        ,3.100226062643091        ,3.1173834986235143        ,3.133635244572521        ,4.999997509605569        ,4.9999975811341475        ,4.999997677486435        ,3.1265553354814046        ,3.106640881465038        ,3.1244075471878383        ,3.1257212423816365       ,3.071537285248495        ,3.0734394100719795        ,4.999997073205902        ,3.082715036777281        ,3.048362166766605        ,4.999997070149889        ,3.049187435889443         ,3.1153197619496256        ,3.1048396867226047        ,3.1185286784020114        ,3.103906512201301        ,3.1203889262631357        ,3.1132000995157956        ,3.125087742118325        ,3.106407973709328        ,3.119161583596059        ,3.1205535194460303        ,3.1187843658597223        ,3.1247013562187003        ,3.120510735279798        ,3.1219285794065796        ,3.1228423774356555        ,3.090439653187103        ,3.10974796383968        ,4.999997702495683        ,4.9999983100840195        ,3.1061631279881325          ,3.0683244281835877        ,3.0890850685102285           ,3.0415375540189475        ,3.0446886153583432        ,3.0592112010154677        ,3.116290252708341        ,4.999998115917833        ,3.1328293068602466        ,4.9999980479169235        ,3.1247920580968955        ,3.116438945426476        ,3.1327149120884394         ,3.047248609742371           ,3.053779631895772        ,3.0620612785488084        ,3.065440994497524        ,3.098397638720138        ,4.999996966246385        ,3.06455336221905        ,3.0894096074267012        ,3.0438843826932227        ,4.999997069766711 };





        //System.out.println();
        //System.out.println("+++++++++++++++++перше набл++++++++++++++++++++++++++++++++++++++++");
        //for(int i=0;i<b.length;i++){
        //        u0[i] = h;
        //        System.out.println((u0[i]));
        //    }
        Text.append("\nКінець обрахунку першого наближення");

        //System.out.println();
        //System.out.println("++++++++++++++U1+++++++++++++++++++++++++++++++++++++++++++");

        for(int i=0;i<b.length;i++){
            //u0[i] = h;
            A.addValue(i, i, 1.0/eps);///////////////////////////
        }
        Text.append("\nПочаток LU-розкладу");
        lu = new LUFactorization(A);
        Text.append("\nКінець LU-розкладу");

        Text.append("\nПочаток ітераційного процесу");
        u1 = null;
        double[] B = new double[b.length];
        int iter = -1;
        iTemp = 1;
        while(true){

            if(iter%10==0){
                this.getRes();
                iTemp++;
            }
            //System.out.println("перевірка:"+iter);
            iter++;
            Text.append("\nІтерація № "+iter);
            Text.setCaretPosition(Text.getText().length());
            for(int i=0;i<b.length;i++){
                B[i]= b[i] + (penalty(u0[i], i))/eps;///////////////////////////////////////
                //System.out.println(penalty(u0[i], i));
            }
            u1 = lu.calculate(B);
            //System.out.println("++++++++++++++++U"+(iter+1)+"++++++++++++++++++++++++++++++++++++++++");
            //for(int i=0;i<b.length;i++){
            //    System.out.println((u1[i]));
            //}
            //System.out.println();
            



            //if(check(u1, u0)){
            //    Text.append("\n\n\n Кінець!!! ");
            //    Text.setCaretPosition(Text.getText().length());

               // break;
                
            //}
            if(iter==MaxIter+1){
                /*System.out.println();
                System.out.println("res"+MaxIter+" = [");
                for (int i = 0; i < u1.length; i++) {
                System.out.print(u1[i]+"\t");
                }
                System.out.println(" ];");*/
                
                
                break;
            }
            u0 = u1;

            try {
                Thread.sleep(100);
            } catch (InterruptedException ignore) {}
        }

        PrintWriter pw =  null;
        try {
            pw = new PrintWriter(new BufferedOutputStream(new FileOutputStream(outPath)));
            pw.println(u1.length + mas.length);
        if(mas.length>0){
            int j;
            for (j = 0; j < mas[0].getNodeNumber(); j++) {
                pw.println(u1[j]);
            }

            for(int i=0; i<mas.length-1; i++){
                int k=0;
                pw.println(mas[i].getValue());
                while(mas[i+1].getNodeNumber() - mas[i].getNodeNumber()-k!=1){
                    pw.println(u1[j]);
                    j++;
                    k++;
                }
            }

            pw.println(mas[mas.length-1].getValue());

            for (int i = j; i < u1.length; i++) {
                pw.println(u1[i]);
            }
        }else{
            for (int i = 0; i < u1.length; i++) {
                pw.println(u1[i]);
            }
        }

        } catch (FileNotFoundException ex) {
            Logger.getLogger(MyPenaltyIterationOld.class.getName()).log(Level.SEVERE, null, ex);
        }finally{
            pw.close();
        }
        

        return null;
    }

    public void getRes(){
        //PrintWriter pw =  null;
            //pw = new PrintWriter(new BufferedOutputStream(new FileOutputStream(outPath)));
            //pw = new PrintWriter(new BufferedOutputStream(System.out));
            //pw.println(u1.length + mas.length);
            System.out.println();
            System.out.print("if(i=="+iTemp+")\nres=[");
        if(mas.length>0){
            int j;
            for (j = 0; j < mas[0].getNodeNumber(); j++) {
                System.out.print(u1[j]+"\t");
            }

            for(int i=0; i<mas.length-1; i++){
                int k=0;
                System.out.print(mas[i].getValue()+"\t");
                while(mas[i+1].getNodeNumber() - mas[i].getNodeNumber()-k!=1){
                    System.out.print(u1[j]+"\t");
                    j++;
                    k++;
                }
            }

            System.out.print(mas[mas.length-1].getValue()+"\t");

            for (int i = j; i < u1.length; i++) {
                System.out.print(u1[i]+"\t");
            }
        }else{
            for (int i = 0; i < u1.length; i++) {
                System.out.print(u1[i]+"\t");
            }
        }
            System.out.print("];");
            System.out.println("\nend");
            //pw.close();
    }

    @Override
    protected void done() {
        Toolkit.getDefaultToolkit().beep();
        Text.append("КІНЕЦЬ!!!");
//        pb.setIndeterminate(false);
    }
}
